from django.shortcuts import render
from django.core.files.base import ContentFile
from django.db.models import Q

from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.decorators import api_view, permission_classes
from rest_framework import serializers
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter, inline_serializer
from drf_spectacular.types import OpenApiTypes

from account.serializer import AccountSerializer
from core.response import AppResponse
from core.serializer import ResponseSerializer
from system.models import Block
from .models import Diy, Ware, Like, Collect, Browse
from .serializer import CollectSerializer, DiyWareSerializer, LikeSerializer, WareSerializer, LikeDiySerializer, CollectDiySerializer, BrowseSerializer
from system.wechat import CustomStorage

from wechatpy import WeChatClient
from decouple import config
import base64
import uuid


# 首页DIY搜索
@extend_schema(
    description='首页DIY配置单搜索',
    parameters=[
        OpenApiParameter(
            name="search", 
            type=OpenApiTypes.STR, 
            required=False,
            location=OpenApiParameter.QUERY,
            description="搜索关键字",
        ),
    ],
    request=None,
    responses=ResponseSerializer
)
@api_view(['GET'])
@permission_classes([AllowAny])
def search_diy(request):
    search = request.GET.get('search')
    queryset = Diy.objects.filter(share=True)
    # 默认手机按倒序前50条
    if search:
        queryset = queryset.filter(Q(title__icontains=search) | Q(desc__icontains=search))[:50]
    else:
        queryset = queryset.order_by('-update_time')[:50]
    serializer = DiyWareSerializer(queryset, many=True)
    return AppResponse(serializer.data)


@extend_schema(
    description='个人中心详情',
    request=None,
    responses=ResponseSerializer
)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def board(request):
    response = {
        'diy': Diy.objects.filter(account = request.user.account_set.first()).count(),
        'like': Like.objects.filter(account = request.user.account_set.first()).count(),
        'collect': Collect.objects.filter(account = request.user.account_set.first()).count(),
        'browse': Browse.objects.filter(account = request.user.account_set.first()).count(),
    }
    return AppResponse(response)


# DIY详情
@extend_schema(
    description='DIY详情',
    parameters=[
        OpenApiParameter(
            name="uuid", 
            type=OpenApiTypes.STR, 
            required=True,
            location=OpenApiParameter.QUERY,
            description="配置单UUID",
        ),
    ],
    request=None,
    responses=ResponseSerializer
)
@api_view(['GET'])
@permission_classes([AllowAny])
def detail(request, uuid):
    queryset = Diy.objects.filter(uuid=uuid).first()
    if not queryset:
        return AppResponse(message='配置单不存在', status=2)
    serializer = DiyWareSerializer(queryset, context={"request": request})
    raw_data = serializer.data
    # 是否是自己的DIY, 或者是匿名用户
    if request.user.is_anonymous:
        raw_data['owner'] = False
    else:
        raw_data['owner'] = queryset.account == request.user.account_set.first()
    return AppResponse(raw_data)


@extend_schema(
    description='获取AI推荐',
    request=None,
    responses=ResponseSerializer
)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def ai_recommendation(request):
    account = request.user.account_set.first()
    # 获取用户的点赞、收藏、浏览,制作
    likes = Like.objects.filter(account =account).all()
    collects = Collect.objects.filter(account = account).all()
    browse = Browse.objects.filter(account = account).all()
    diys = Diy.objects.filter(account = account).all()
    # 遍历
    ask_str = """
    请为我推荐一份电脑配置单,根据我从前浏览过的配置单,点赞过的配置单,收藏过的配置单,以及自己制作的配置单来创建
    """
    ask_str += f"\n我点赞过的配置单如下: \n\n"
    for like in likes:
        q = Diy.objects.filter(uuid=like.diy.uuid).first()
        all = Ware.objects.filter(diy=q).all()
        ask_str += f"\n配置单名: {q.title}\n配置单描述:{q.desc}"
        for a in all:
            ask_str += f"""
    配置元件: {a.title}
    品牌: {a.brand}
    价格: {a.price}
    图片: {a.image}
    描述: {a.desc}
    数量: {a.count}
            """

    ask_str += f"\n\n我收藏过的配置单如下: \n\n"
    for collect in collects:
        q = Diy.objects.filter(uuid=collect.diy.uuid).first()
        all = Ware.objects.filter(diy=q).all()
        ask_str += f"\n配置单名: {q.title}\n配置单描述:{q.desc}"
        for a in all:
            ask_str += f"""
    配置元件: {a.title}
    品牌: {a.brand}
    价格: {a.price}
    图片: {a.image}
    描述: {a.desc}
    数量: {a.count}
            """

    ask_str += f"\n\n我浏览过的配置单如下: \n\n"
    for b in browse:
        q = Diy.objects.filter(uuid=b.diy.uuid).first()
        all = Ware.objects.filter(diy=q).all()
        ask_str += f"\n配置单名: {q.title}\n配置单描述:{q.desc}"
        for a in all:
            ask_str += f"""
    配置元件: {a.title}
    品牌: {a.brand}
    价格: {a.price}
    图片: {a.image}
    描述: {a.desc}
    数量: {a.count}
            """

    ask_str += f"\n\n我制作的配置单如下: \n\n"
    for d in diys:
        all = Ware.objects.filter(diy=d).all()
        ask_str += f"\n配置单名: {d.title}\n配置单描述:{d.desc}"
        for a in all:
            ask_str += f"""
    配置元件: {a.title}
    品牌: {a.brand}
    价格: {a.price}
    图片: {a.image}
    描述: {a.desc}
    数量: {a.count}
            """

    ask_str+="""\n请你根据以上信息,并通过互联网最新信息,根据我所提供的配置元件,品牌,价格,图片,描述,数量等信息,制作一份电脑配置单,并返回json数据格式
    回答请以文本形式返回只包含数据格式下的格式数据(去掉markdown格式):
    {
        "title": "配置单名",
        "desc": "配置单描述",
        "wares": [
            { "title": "配置元件名", "brand": "型号", "price": "价格","desc": "描述", "count": "数量" },
            { "title": "配置元件名", "brand": "型号", "price": "价格","desc": "描述", "count": "数量" },
            { "title": "配置元件名", "brand": "型号", "price": "价格", "desc": "描述", "count": "数量" }
            ]   
    }
    """
    # ask_str+="\n请你根据以上信息,并通过互联网最新信息,根据我所提供的配置元件,品牌,价格,图片,描述,数量等信息,制作一份电脑配置单"
    # 调用AI接口
    from common.ask_gpt35 import GPT3
    gpt3 = GPT3()
    response = gpt3.ask_question(ask_str)



    # 解析返回结果
    print(response)
    return AppResponse(code=1,data=response,message=response)
    pass

# 我的DIY
class DiyViewSet(viewsets.ModelViewSet):
    queryset = Diy.objects.all()
    serializer_class = DiyWareSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return self.queryset.filter(account = self.request.user.account_set.first())
    
    # 重写list方法
    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset().order_by('-create_time')
        serializer = self.get_serializer(queryset, many=True)
        return AppResponse(serializer.data)
    
    # 重写create方法
    def create(self, request, *args, **kwargs):
        print('访问者IP', request.META.get('HTTP_X_FORWARDED_FOR'))
        blocked = Block.objects.filter(address = request.META.get('HTTP_X_FORWARDED_FOR', '').strip()).count()
        if blocked > 0:
            print('IP已被封禁', request.META.get('HTTP_X_FORWARDED_FOR'))
            return AppResponse(message='您的IP已被封禁', code=1)
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        diy_uuid = uuid.uuid4().hex[:10]
        serializer.save(account = request.user.account_set.first(), uuid=diy_uuid)
        # 获取小程序码
        wx_client = WeChatClient(config('WEIXIN_APP_ID'), config('WEIXIN_APP_SECRET'), session=CustomStorage())
        try:
            response = wx_client.wxa.get_wxa_code_unlimited(
                    'id=' + diy_uuid,
                    page='pages/detail/detail', 
                )
            serializer.instance.weapp_qrcode.save(f'share_{diy_uuid}.png', ContentFile(response.content))
            return AppResponse(serializer.data)
        except Exception as e:
            print('小程序码生成失败', e)
        return AppResponse(serializer.data)
    
    # 重写update方法
    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        # get wares
        if 'wares' in request.data:
            wares = request.data.pop('wares')
            # remove old wares and add new wares
            Ware.objects.filter(diy=instance).delete()
            Ware.objects.bulk_create([Ware(diy=instance, **ware) for ware in wares])
        # update diy
        serializer = self.get_serializer(instance, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        return AppResponse(serializer.data)
    
    # 重写destroy方法
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return AppResponse()
    

# 我的元件
class WareViewSet(viewsets.ModelViewSet):
    queryset = Ware.objects.all()
    serializer_class = WareSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return self.queryset.filter(account = self.request.user.account_set.first())
    

# 我的点赞
class LikeViewSet(viewsets.ModelViewSet):
    queryset = Like.objects.all()
    serializer_class = LikeDiySerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return self.queryset.filter(account = self.request.user.account_set.first())
    
    # 重写list方法
    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset().order_by('-create_time')
        serializer = self.get_serializer(queryset, many=True)
        return AppResponse(serializer.data)

    # 重写create方法
    def create(self, request, *args, **kwargs):
        serializer = LikeSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # catch unique exception
        try:
            serializer.save(account = request.user.account_set.first())
        except Exception as e:
            return AppResponse(message='已点赞', code=1)
        return AppResponse(serializer.data)
    
    # 重写destroy方法
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return AppResponse()
    

# 我的收藏
class CollectViewSet(viewsets.ModelViewSet):
    queryset = Collect.objects.all()
    serializer_class = CollectDiySerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return self.queryset.filter(account = self.request.user.account_set.first())
    
    # 重写list方法
    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset().order_by('-create_time')
        serializer = self.get_serializer(queryset, many=True)
        return AppResponse(serializer.data)
    
    # 重写create方法
    def create(self, request, *args, **kwargs):
        serializer = CollectSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # catch unique exception
        try:
            serializer.save(account = request.user.account_set.first())
        except Exception as e:
            return AppResponse(message='已收藏', code=1)
        return AppResponse(serializer.data)
    
    # 重写destroy方法
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return AppResponse()
    

# 我的浏览
class BrowseViewSet(viewsets.ModelViewSet):
    queryset = Browse.objects.all()
    serializer_class = BrowseSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return self.queryset.filter(account = self.request.user.account_set.first())
    
    # 重写create方法
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save(account = request.user.account_set.first())
        return AppResponse(serializer.data)
    
    # 重写destroy方法
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return AppResponse()
